package com.example.opengldemo.fbo;

import java.io.IOException;
import java.io.InputStream;

import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.view.MotionEvent;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.View;

import com.example.opengldemo.R;
import com.example.opengldemo._07_texture.TextureImage;
import com.example.opengldemo._09_OBJ.ObjDemo;
import com.example.opengldemo.base.Obj_Vertex_Normal_Texcoors_Demo;
import com.example.opengldemo.base.TextureRect;
import com.example.opengldemo.util.LoadUtil;
import com.example.opengldemo.util.MatrixState;
import com.example.opengldemo.util.TextureUtil;

@SuppressLint("NewApi") 
public class MySurfaceView extends GLSurfaceView
{
	private final float TOUCH_SCALE_FACTOR = 180.0f/320;
    private SceneRenderer mRenderer;
    
    private float mPreviousY;
    private float mPreviousX;
    float ratio;

    static final int GEN_TEX_WIDTH=1024;
    static final int GEN_TEX_HEIGHT=1024;
    
    int SCREEN_WIDTH;
    int SCREEN_HEIGHT;
	public MySurfaceView(Context context) {
        super(context);
        this.setEGLContextClientVersion(3);
        mRenderer = new SceneRenderer();
        setRenderer(mRenderer);
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }
    @SuppressLint("ClickableViewAccessibility") 
    @Override 
    public boolean onTouchEvent(MotionEvent e) 
    {
        float y = e.getY();
        float x = e.getX();
        switch (e.getAction()) {
        case MotionEvent.ACTION_MOVE:
            float dy = y - mPreviousY;
            float dx = x - mPreviousX;
            mRenderer.yAngle += dx * TOUCH_SCALE_FACTOR;
            mRenderer.xAngle+= dy * TOUCH_SCALE_FACTOR;
            requestRender();
        }
        mPreviousY = y;
        mPreviousX = x;
        return true;
    }

	private class SceneRenderer implements Renderer
    {
		float yAngle;
    	float xAngle;

		
		int frameBufferId;
		int renderDepthBufferId;
		int textureId;
		int textureIdGHXP;
		TextureRect tr;
		Obj_Vertex_Normal_Texcoors_Demo lovo;
		
		public void initFRBuffers()
		{
			int tia[]=new int[1];
			GLES30.glGenFramebuffers(1, tia, 0);
			frameBufferId=tia[0];

			GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, frameBufferId);
			
			GLES30.glGenRenderbuffers(1, tia, 0);
			renderDepthBufferId=tia[0];

			GLES30.glBindRenderbuffer(GLES30.GL_RENDERBUFFER, renderDepthBufferId);

			GLES30.glRenderbufferStorage(GLES30.GL_RENDERBUFFER, 
					GLES30.GL_DEPTH_COMPONENT16,GEN_TEX_WIDTH, GEN_TEX_HEIGHT);
			
			int[] tempIds = new int[1];
			GLES30.glGenTextures
    		(
    				1,
    				tempIds,
    				0
    		);
			textureId=tempIds[0];
			GLES30.glBindTexture(GLES30.GL_TEXTURE_2D,textureId);
			GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,
					GLES30.GL_TEXTURE_MIN_FILTER,GLES30.GL_LINEAR);
			GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,
					GLES30.GL_TEXTURE_MAG_FILTER,GLES30.GL_LINEAR);
			GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,
					GLES30.GL_TEXTURE_WRAP_S,GLES30.GL_CLAMP_TO_EDGE);
			GLES30.glTexParameterf(GLES30.GL_TEXTURE_2D,
					GLES30.GL_TEXTURE_WRAP_T,GLES30.GL_CLAMP_TO_EDGE); 
			GLES30.glTexImage2D
        	(
        		GLES30.GL_TEXTURE_2D,
        		0,
        		GLES30.GL_RGBA,
        		GEN_TEX_WIDTH,
        		GEN_TEX_HEIGHT,
        		0,
        		GLES30.GL_RGBA,
        		GLES30.GL_UNSIGNED_BYTE,
        		null
        	);
			GLES30.glFramebufferTexture2D
            (
            	GLES30.GL_FRAMEBUFFER,
            	GLES30.GL_COLOR_ATTACHMENT0,
            	GLES30.GL_TEXTURE_2D,
            	textureId,
            	0
            );
			GLES30.glFramebufferRenderbuffer
        	(
        		GLES30.GL_FRAMEBUFFER,
        		GLES30.GL_DEPTH_ATTACHMENT,
        		GLES30.GL_RENDERBUFFER,
        		renderDepthBufferId
        	);
		}
		
		public void generateTextImage()
		{

			GLES30.glViewport(0, 0, GEN_TEX_WIDTH, GEN_TEX_HEIGHT);

			GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, frameBufferId);

			GLES30.glClear( GLES30.GL_DEPTH_BUFFER_BIT | GLES30.GL_COLOR_BUFFER_BIT);

            MatrixState.setProjectFrustum(-ratio, ratio, -1, 1, 2, 100);
			MatrixState.setCamera(0,0,0,0f,0f,-1f,0f,1.0f,0.0f);


            MatrixState.pushMatrix();
            MatrixState.translate(0, -16f, -80f);

            MatrixState.rotate(yAngle, 0, 1, 0);
            MatrixState.rotate(xAngle, 1, 0, 0);
            if(lovo!=null)
            {
            	lovo.drawSelf(textureIdGHXP);
            }
            MatrixState.popMatrix();
		}
		
		public void drawShadowTexture()
		{

			GLES30.glViewport(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
			GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);

			GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT |GLES30.GL_COLOR_BUFFER_BIT);

            MatrixState.setProjectFrustum(-ratio, ratio, -1, 1, 2, 100);
			MatrixState.setCamera(0,0,3,0f,0f,0f,0f,1.0f,0.0f);
            MatrixState.pushMatrix();
            tr.drawSelf(textureId);
            MatrixState.popMatrix();
		}
        public void onDrawFrame(GL10 gl) 
        {
            generateTextImage();
            drawShadowTexture();
        }

        public void onSurfaceChanged(GL10 gl, int width, int height)
        {
        	SCREEN_WIDTH=width;
        	SCREEN_HEIGHT=height;
            ratio = (float) width / height;
            initFRBuffers();
			tr=new TextureRect(MySurfaceView.this,ratio);
			MatrixState.setLightLocation(40, 100, 20);
        }
        public void onSurfaceCreated(GL10 gl, EGLConfig config) 
        {   

        	GLES30.glClearColor(0.3f,0.3f,0.3f,1.0f);

        	GLES30.glEnable(GLES30.GL_DEPTH_TEST);
        	GLES30.glEnable(GLES30.GL_CULL_FACE);

            MatrixState.setInitStack();
            textureIdGHXP= TextureUtil.getTextureId(MySurfaceView.this , R.drawable.android_robot0 , null , false);

			LoadUtil.getLoadObj(MySurfaceView.this, "obj/ch_t.obj",
					new LoadUtil.CreateObjectLoader() {
						@Override
						public void create(View view, float[] vertexArray, float[] normalArray, float[] texcoorsArray) {
							lovo = new Obj_Vertex_Normal_Texcoors_Demo(view , vertexArray , normalArray , texcoorsArray) ;
						}
					});
        }
    }
}
